﻿using Common.FrontEnd;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Util;

namespace FrontEnd
{
    /// <summary>
    /// A Data object that holds data of primitive type float.
    /// </summary>
    public class FloatData : Object, IData, ICloneable, IFloatData
    {
        private float[] values;
        private int sampleRate;
        private long firstSampleNumber;
        private long collectTime;

        /**
        /// Constructs a Data object with the given values, sample rate, collect time, and first sample number.
         *
        /// @param values            the data values
        /// @param sampleRate        the sample rate of the data
        /// @param firstSampleNumber the position of the first sample in the original data
         */
        public FloatData(float[] values, int sampleRate, long firstSampleNumber) 
            :this(values, sampleRate, firstSampleNumber* 1000 / sampleRate, firstSampleNumber)
        {
            
        }

        /**
        /// Constructs a Data object with the given values, sample rate, collect time, and first sample number.
         *
        /// @param values            the data values
        /// @param sampleRate        the sample rate of the data
        /// @param collectTime       the time at which this data is collected
        /// @param firstSampleNumber the position of the first sample in the original data
         */
        public FloatData(float[] values, int sampleRate,
                         long collectTime, long firstSampleNumber) 
        {
            this.values = values;
            this.sampleRate = sampleRate;
            this.collectTime = collectTime;
            this.firstSampleNumber = firstSampleNumber;
        }


        /**
        /// @return the values of this data.
         */
        public float[] getValues() 
        {
            return values;
        }


        /**
        /// @return the sample rate of this data.
         */
        public int getSampleRate() 
        {
            return sampleRate;
        }


        /**
        /// @return the position of the first sample in the original data. The very first sample number is zero.
         */
        public long getFirstSampleNumber() 
        {
            return firstSampleNumber;
        }


        /**
        /// Returns the time in milliseconds at which the audio data is collected.
         *
        /// @return the difference, in milliseconds, between the time the audio data is collected and midnight, January 1,
        ///         1970
         */
        public long getCollectTime() 
        {
            return collectTime;
        }

      
        /** Converts a given Data-object into a <code>FloatData</code> if possible.
        ///  @param data
         */
        public static FloatData toFloatData(IData data) 
        {
            FloatData convertData;
            if (data is FloatData)
                convertData = (FloatData) data;
            else if (data is DoubleData) 
            {
                DoubleData dd = (DoubleData) data;
                convertData = new FloatData(MatrixUtils.double2float(dd.Values), dd.getSampleRate(),
                        dd.getFirstSampleNumber());
            } else
                throw new ArgumentException("data type '" + data.GetType().Name + "' is not supported");

            return convertData;
        }


        object ICloneable.Clone()
        {
            try
            {
                //
                //The MemberwiseClone method creates a shallow copy by creating a new object, 
                //and then copying the nonstatic fields of the current object to the new object
                FloatData data = (FloatData)this.MemberwiseClone();
                return data;
            }
            catch (Exception e)
            {
                throw new SystemException(e.ToString());
            }
        }

        void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
        {
            throw new NotImplementedException();
        }
    }
}
